home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 August: Tool Chest / Dev.CD Aug 95 TC / Dev.CD Aug 95 TC.toast / Sample Code / Snippets / Interapplication Communication / FinderOpenSelection / FinderOpenSel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-09  |  28.0 KB  |  777 lines  |  [TEXT/MPS ]

  1. /* FinderOpenSel 1.1 */
  2. /* This sample shows how to use the Finder OpenSelection AppleEvent. */
  3. /* You can use this event to launch applications or files, or open Finder windows */
  4. /* Version 1.1 here also shows you how to launch an application remotely */
  5. /* Written  by C.K. Haun <TR> */
  6. /* Apple Developer Tech Support */
  7. /* April 1992, Cupertino, CA USA */
  8. /* Of course, Copyright 1991-1992, Apple Computer Inc. */
  9. #include <Types.h>
  10. #include <memory.h>
  11. #include <Packages.h>
  12. #include <Errors.h>
  13. #include <quickdraw.h>
  14. #include <fonts.h>
  15. #include <dialogs.h>
  16. #include <windows.h>
  17. #include <menus.h>
  18. #include <events.h>
  19. #include <OSEvents.h>
  20. #include <Desk.h>
  21. #include <diskinit.h>
  22. #include <OSUtils.h>
  23. #include <resources.h>
  24. #include <toolutils.h>
  25. #include <AppleEvents.h>
  26. #include <EPPC.h>
  27. #include <GestaltEqu.h>
  28. #include <PPCToolbox.h> 
  29. #include <Processes.h>
  30. #include <Balloons.h>
  31. #include <ALiases.h>
  32. #include <Processes.h>
  33. #include <StandardFile.h>
  34. #include <Folders.h>
  35. /* prototypes */
  36. void InitalizeApp(void);
  37. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  38. void DrawMain(WindowPtr drawIt);
  39. Boolean DoSelected(long val);
  40. OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN, ProcessInfoRecPtr infoRecToFill);
  41. OSErr OpenSelection(short which);
  42. void InitAEStuff(void);
  43. void DoHighLevel(EventRecord *AERecord);
  44. void DoDaCall(MenuHandle themenu, long theit);
  45. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  46. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  47. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  48. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  49. void SampleHelpDialog(void);
  50. OSErr GetPathAndName(Str255 fullPath, Str255 appName);
  51. OSErr BrowseFerMe(void);
  52. pascal Boolean FinderFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  53. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
  54. pascal Boolean idleProc(EventRecord *eventIn, long *sleep, RgnHandle *mouseRgn);
  55.  
  56. long trashDirID;
  57. short trashVRef;
  58.  
  59. /* one external */
  60. extern void _DataInit();                                    /* this is the C initialization code */
  61.  
  62. #define kWaitDialog 132
  63. #define kMBarID 128
  64. #define kAppleMenu 128
  65. #define kFileMenu 129
  66. #define kEditMenu 130
  67. #define kToolsMenu 131
  68. #define kResumeMask 1 /* bit of message field for resume vs. suspend */
  69. #define kSampHelp 129
  70. #define kAboutBox 128
  71. #define kHelpString 128
  72. #define kNewItem 1
  73. #define kOpenItem 2
  74. #define kCloseItem 3
  75. #define kSaveItem 4
  76. #define kSaveAsItem 5
  77. #define kFileBlank1 6
  78. #define kPageSetupItem 7
  79. #define kPrintItem 8
  80. #define kFileBlank2 9
  81. #define kQuitItem 10
  82. #define kBadSystem 130
  83. #define kOpenAppItem 1
  84. #define kOpenWindowItem 2
  85. #define kRemoteLaunchItem 3
  86. #define kTextType 'TEXT'
  87. #define kTextResID 128
  88. #define kMyWindowResID 128
  89. #define aeSelectionKeyword 'fsel'
  90. #define kAEOpenSelection 'sope'
  91. #define kFinderType 'FNDR'
  92. #define kSysCreator 'MACS'
  93. #define kPathDialog 131
  94. #define kEditLineItem 4
  95. #define kColon ':'
  96. enum  {
  97.     kGenStrings = 128, kPPCPrompt1 = 1, kPPCPrompt2
  98. };
  99.  
  100. AEIdleUPP gAEIdleUPP;
  101.  
  102. Handle gMymenu;                                             /* my menu bar handle */
  103. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle;
  104. Boolean gQuit, gInBackground;
  105. EventRecord gERecord;
  106. AEDesc gTheAddress;
  107. WindowPtr myWindow = 0;
  108. ProcessSerialNumber gOurSN;
  109. short gHelpItem;
  110. LocationNameRec theLoc;
  111. PortInfoRec theRec;
  112. PPCPortRec myPortName;
  113. LocationNameRec myLoc;
  114. AEDesc myAddressDesc;
  115. TargetID theID;
  116. PPCFilterUPP gPPCFilterUPP;
  117.  
  118. #ifdef powerc
  119.    QDGlobals    qd;
  120. #endif
  121.  
  122. #pragma segment Main
  123. main()
  124. {
  125.     WindowPtr twindow;
  126.     
  127.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  128.     InitalizeApp();
  129.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  130.        
  131.     do {
  132.         WaitNextEvent(everyEvent, &gERecord, 5, nil);
  133.         switch (gERecord.what) {
  134.             
  135.             case nullEvent:
  136.                 
  137.                 /* no nul processing in this sample */
  138.                 break;
  139.             case updateEvt:
  140.                 DrawMain((WindowPtr)gERecord.message);      /* draw whatever window needs an update */
  141.                 break;
  142.             case mouseDown:
  143.                 
  144.                 /* first see where the hit was */
  145.                 
  146.                 switch (FindWindow(gERecord.where, &twindow)) {
  147.                     
  148.                     case inDesk:                            /* if they hit in desk, then the process manager */
  149.                         break;                              /* will switch us out, we don't need to do anything */
  150.                     case inMenuBar:
  151.                         DoSelected(MenuSelect(gERecord.where));
  152.                         break;
  153.                         
  154.                     case inSysWindow:
  155.                         /* pass to the system */
  156.                         SystemClick(&gERecord, twindow);
  157.                         break;
  158.                         
  159.                     case inContent:
  160.                         /* Handle content and control clicks here */
  161.                         break;
  162.                         
  163.                     case inDrag:
  164.                         if (twindow == FrontWindow())
  165.                             DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  166.                         break;
  167.                         
  168.                     case inGrow:
  169.                         /* Call GrowWindow here if you have a grow box */
  170.                         break;
  171.                         
  172.                     case inGoAway:
  173.                         /* Click in Close box */
  174.                         break;
  175.                         
  176.                 }
  177.             case mouseUp:
  178.                 /* don't care */
  179.                 break;
  180.                 
  181.                 /* same action for key or auto key */
  182.                 
  183.             case keyDown:
  184.             case autoKey:
  185.                 if (gERecord.modifiers & cmdKey)
  186.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  187.                 break;
  188.                 
  189.             case keyUp:
  190.                 /* don't care */
  191.                 break;
  192.                 
  193.             case diskEvt:
  194.                 /* I don't do anything special for disk events, this just passes them */
  195.                 /* to a function that checks for an error on the mount */
  196.                 DoDiskEvents(gERecord.message);
  197.                 break;
  198.                 
  199.             case activateEvt:
  200.                 if (gERecord.modifiers & activeFlag)
  201.                     DrawMain((WindowPtr)gERecord.message);
  202.                 break;
  203.                 
  204.             case networkEvt:
  205.                 /* don't care */
  206.                 break;
  207.                 
  208.             case driverEvt:
  209.                 /* don't care */
  210.                 break;
  211.                 
  212.             case app4Evt:
  213.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  214.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  215.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  216.                         break;
  217.                 }
  218.                 break;
  219.                 
  220.                 /* This dispatches high level events (AppleEvents, for example) */
  221.                 /* to our dispatch routine.  This is NEW in the event loop for */
  222.                 /* System 7 */
  223.                 
  224.             case kHighLevelEvent:
  225.                 DoHighLevel(&gERecord);
  226.                 break;
  227.                 
  228.             default:
  229.                 break;
  230.                 
  231.         }
  232.     }
  233.             while (gQuit != true);
  234.     
  235. }
  236.  
  237. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  238. /* like to perform some action or just know when a DA is opened in your */
  239. /* layer.  Can be handy to track memory problems when a DA is opened */
  240. /* with an Option-open */
  241. void DoDaCall(MenuHandle themenu, long theit)
  242. {
  243.     long qq;
  244.     char DAname[255];
  245.     GetItem(themenu, theit, &DAname);
  246.     qq = OpenDeskAcc(DAname);
  247. }
  248.  
  249. /* end DoDaCall */
  250.  
  251. /* DoDiskEvents just checks the error code from the disk mount, */
  252. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  253. /* You can do much more here if you care about what disks are */
  254. /* in the drive */
  255. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  256. {
  257.     short hival, loval, tommy;
  258.     Point fredpoint =  {
  259.         40, 40
  260.     };
  261.     hival = HiWord(dinfo);
  262.     loval = LoWord(dinfo);
  263.     if (hival != noErr)                                     /* something happened */ {
  264.         tommy = DIBadMount(fredpoint, dinfo);
  265.     }
  266. }
  267.  
  268. /* draws my window.  Pretty simple */
  269. void DrawMain(WindowPtr drawIt)
  270. {
  271.     Handle theText;
  272.     BeginUpdate(drawIt);
  273.     SetPort(drawIt);
  274.     EraseRect(&drawIt->portRect);
  275.     theText = GetResource(kTextType, kTextResID);
  276.     if (theText) {
  277.         Rect textRect;
  278.         HLock(theText);
  279.         HUnlock(theText);
  280.         textRect = drawIt->portRect;
  281.         InsetRect(&textRect, 5, 5);
  282.         TextBox(*theText, GetHandleSize(theText), &textRect, 0);
  283.         ReleaseResource(theText);
  284.     }
  285.     EndUpdate(drawIt);
  286. }
  287.  
  288. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  289. /* mught be handy someday */
  290. Boolean DoSelected(long val)
  291. {
  292.     short loval, hival;
  293.     Boolean returnVal = false;
  294.     loval = LoWord(val);
  295.     hival = HiWord(val);
  296.     
  297.     switch (hival) {                                        /* switch off the menu number selected */
  298.         
  299.         case kAppleMenu:                                    /* Apple menu */
  300.             if (loval != 1) {                               /* if this was not About, it's a DA */
  301.                 DoDaCall(gAppleMenuHandle, loval);
  302.             } else {
  303.                 Alert(kAboutBox, nil);                      /* do about box */
  304.             }
  305.             returnVal = true;
  306.             break;
  307.             
  308.         case kFileMenu:                                     /* File menu */
  309.             switch (loval) {
  310.                 
  311.                 case kQuitItem:
  312.                     gQuit = true;                           /* only  item */
  313.                     returnVal = true;
  314.                     break;
  315.                     
  316.                 default:
  317.                     break;
  318.             }
  319.             break;
  320.             
  321.         case kEditMenu:
  322.             /* edit menu junk */
  323.             /* don't care */
  324.             break;
  325.             
  326.         case kToolsMenu:
  327.             /* add all your test stuff here */
  328.             OpenSelection(loval);
  329.             break;
  330.             
  331.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  332.             /* I only care about this item.  If anything else is returned here, I don't know what */
  333.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  334.             /* Apple reserves the right to add and change things in the Help menu */
  335.             if (loval == gHelpItem)
  336.                 SampleHelpDialog();
  337.             break;
  338.             
  339.     }
  340.     HiliteMenu(0);
  341.     return(returnVal);
  342. }
  343.  
  344. /* InitAEStuff installs my appleevent handlers */
  345. void InitAEStuff(void)
  346. {    
  347.     OSErr aevtErr = noErr;
  348.     long aLong = 0;
  349.     Boolean gHasAppleEvents = false;
  350.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  351.     *   then we exit */
  352.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  353.     /* The following series of calls installs all our AppleEvent Handlers.
  354.     *   These handlers are added to the application event handler list that 
  355.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  356.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  357.     *   list of handlers and dispatch to it if there is one.
  358.     */
  359.     if (gHasAppleEvents) {
  360.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, 
  361.              NewAEEventHandlerProc(AEOpenHandler),0, false);
  362.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
  363.              NewAEEventHandlerProc(AEOpenDocHandler),0, false);
  364.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
  365.              NewAEEventHandlerProc(AEQuitHandler), 0, false);
  366.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, 
  367.              NewAEEventHandlerProc(AEPrintHandler),0, false);
  368.              
  369.          if (aevtErr)  ExitToShell();
  370.          
  371.          /* create a UPP for the AppleEvent idle proc */
  372.          gAEIdleUPP = NewAEIdleProc(idleProc);
  373.  
  374.        } 
  375.     else ExitToShell();
  376.     
  377. }
  378. /* end InitAEStuff */
  379.  
  380. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  381. /* easy for me to say, huh? */
  382. void DoHighLevel(EventRecord *AERecord)
  383. {
  384.     
  385.     AEProcessAppleEvent(AERecord);
  386.     
  387. }
  388.  
  389. /* end DoHighLevel */
  390.  
  391. /* This is the standard Open Application event.  */
  392. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  393. {
  394. #pragma unused (messagein,reply,refIn)
  395.     /* we of course don't do anything here in this simple app */
  396.     /* except open our window */
  397.     
  398.     myWindow = GetNewWindow(kMyWindowResID, nil, (WindowPtr)-1);
  399.     return(noErr);
  400. }
  401.  
  402. /* end AEOpenHandler */
  403.  
  404. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  405. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  406. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  407. /* handler will get called. Which means you don't do any initialization of globals here, or */
  408. /* anything else except open then doc.  */
  409. /* SO-- Do NOT assume that you are at app start time in this */
  410. /* routine, or bad things will surely happen to you. */
  411.  
  412. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  413. {
  414. #pragma unused (messagein,refIn,reply)
  415.     /* we of course don't do anything here */
  416.     
  417.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  418. }
  419.  
  420. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  421. {                                                           /* no printing handler in yet, so we'll ignore this */
  422.     /* the operation is functionally identical to the ODOC event, with the additon */
  423.     /* of calling your print routine.  */
  424. #pragma unused (messagein,refIn,reply)
  425.     
  426.     /* we of course don't do anything here */
  427.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  428. }
  429.  
  430. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  431. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  432. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  433. {
  434. #pragma unused (messagein,refIn,reply)
  435.     
  436.     /* prepQuit sets the Stop flag for us.  It does _NOT_ quit, you */
  437.     /* should NEVER quit from an AppleEvent handler.  Calling */
  438.     /* ExitToShell here would blow things up */
  439.     gQuit = true;
  440.     return(noErr);
  441. }
  442.  
  443. /* This is my sample help dialog.  Does not do anything, expand as you need */
  444. void SampleHelpDialog(void)
  445. {
  446.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  447.     short itemhit = 0;
  448.     while (itemhit != 1) {
  449.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  450.     }
  451.     DisposDialog(tdial);
  452. }
  453.  
  454. /* OpenSelection perpares and sends the Finder OpenSelection event */
  455. /* Three choices currently.  If which is 1, then we do an OpenSelection on the file itself. */
  456. /* if which is 2, then we tell the finder to open the directory window containing the file  */
  457. /* if it's 3, then we ask for a remote name and launch remotely */
  458.  
  459. OSErr OpenSelection(short which)
  460. {
  461.     AppleEvent aeEvent, aeReply;
  462.     AEDesc aeDirDesc, listElem;
  463.     OSErr interactErr = noErr;
  464.     FSSpec dirSpec, procSpec;
  465.     AEDesc fileList;
  466.     StandardFileReply myReply;
  467.     OSErr myErr;
  468.     ProcessSerialNumber process;
  469.     AliasHandle DirAlias, FileAlias;
  470.     FSSpecPtr theFileToOpen = nil;
  471.     ProcessInfoRec infoRec;
  472.     Str31 processName;
  473.     Str255 fullPath;
  474.     Str255 appName;
  475.     
  476.     if (which != kRemoteLaunchItem)
  477.         StandardGetFile(nil, -1, nil, &myReply);
  478.     else
  479.         myReply.sfGood = true;                              /* set this since I want to be silent this time */
  480.     if (myReply.sfGood) {
  481.         theFileToOpen = &myReply.sfFile;
  482.         infoRec.processInfoLength = sizeof(ProcessInfoRec);
  483.         infoRec.processName = &processName;
  484.         infoRec.processAppSpec = &procSpec;
  485.         
  486.         /* Browse for the Finder you wish to communicate with */
  487.         
  488.         if (which != kRemoteLaunchItem) {
  489.             /* if less than kRemoteLaunchItem, then we are working locally, find the finder on this machine */
  490.             
  491.             myErr = FindAProcess(kFinderType, kSysCreator, &process, &infoRec);
  492.             if (myErr == noErr)
  493.                 myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
  494.             
  495.         } else {
  496.             
  497.             /* Get a remote finder  */
  498.             myErr = BrowseFerMe();
  499.         }
  500.         if (myErr == noErr) {
  501.             
  502.             /* Create the FinderEvent */
  503.             myErr = AECreateAppleEvent(kFinderType, kAEOpenSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
  504.                                        &aeEvent);
  505.             /* If you want to keep talking to this machine, you can keep this  */
  506.             /* address desc around */
  507.             AEDisposeDesc(&myAddressDesc);
  508.             
  509.             if (myErr == noErr) {
  510.                 /* Now we build all the bits of an OpenSelection event. */
  511.                 /* Basically, we need to create an alias for the item to open, and an alias to the parent */
  512.                 /* folder (directory) of that item. */
  513.                 /* We can also pass a list of files if we want.  */
  514.                 /* You'll notice that for opening a finder window, the file and directory alias both point at the */
  515.                 /* folder itself */
  516.                 /* make a spec for the parent folder */
  517.                 
  518.                 if (which != kRemoteLaunchItem) {
  519.                     FSMakeFSSpec(theFileToOpen->vRefNum, theFileToOpen->parID, nil, &dirSpec);
  520.                     NewAlias(nil, &dirSpec, &DirAlias);
  521.                 }
  522.                 /* Create alias for file */
  523.                 /* if you are opening a window, then you make the file alias the same as the dir alias */
  524.                 switch (which) {
  525.                     
  526.                     case kOpenAppItem:
  527.                         NewAlias(nil, theFileToOpen, &FileAlias);
  528.                         break;
  529.                         
  530.                     case kOpenWindowItem:
  531.                         NewAlias(nil, &dirSpec, &FileAlias);
  532.                         
  533.                         /* I want to set the Finder as the front process after the event  */
  534.                         /* is sent (if I can) so you can see what happened.  Rememeber, app switches */
  535.                         /* don't happen until _after_ (or during) the next WaitNextEvent call */
  536.                         
  537.                         interactErr = AEInteractWithUser(kAEDefaultTimeout, nil, gAEIdleUPP);
  538.                         if (interactErr == noErr)
  539.                             SetFrontProcess(&process);
  540.                         break;
  541.                         
  542.                     case kRemoteLaunchItem:
  543.                         myErr = GetPathAndName(fullPath, appName);
  544.                         if (myErr == noErr) {
  545.                             /* NewAliasMinimalFromFullPath (geez what a lot of typing) creates an alias that does NOT */
  546.                             /* have a file ID, just builds based on what it has, the path.  So we don't need to */
  547.                             /* connect to another machine or file server to make this alias, which is why this thing works. */
  548.                             
  549.                             NewAliasMinimalFromFullPath(appName[0], (Ptr)&appName[1], "", "", &FileAlias);
  550.                             NewAliasMinimalFromFullPath(fullPath[0], (Ptr)&fullPath[1], "", "", &DirAlias);
  551.                         }
  552.                         break;
  553.                 }
  554.                 /* Create the file  list */
  555.                 if (myErr == noErr) {
  556.                     myErr = AECreateList(nil, 0, false, &fileList);
  557.                     
  558.                     /*  create the folder  descriptor */
  559.                     HLock((Handle)DirAlias);
  560.                     AECreateDesc(typeAlias, (Ptr)*DirAlias, GetHandleSize((Handle)DirAlias), &aeDirDesc);
  561.                     HUnlock((Handle)DirAlias);
  562.                     if ((myErr = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDirDesc)) == noErr) {
  563.                         /* done with the desc, kill it */
  564.                         AEDisposeDesc(&aeDirDesc);
  565.                         /*  create the file descriptor and add to aliasList */
  566.                         HLock((Handle)FileAlias);
  567.                         AECreateDesc(typeAlias, (Ptr)*FileAlias, GetHandleSize((Handle)FileAlias), &listElem);
  568.                         HLock((Handle)FileAlias);
  569.                         myErr = AEPutDesc(&fileList, 0, &listElem);
  570.                     }
  571.                     if (myErr == noErr) {
  572.                         
  573.                         AEDisposeDesc(&listElem);
  574.                         
  575.                         /* Add the file alias list to the event */
  576.                         myErr = AEPutParamDesc(&aeEvent, aeSelectionKeyword, &fileList);
  577.                         AEDisposeDesc(&fileList);
  578.                         
  579.                         if (myErr == noErr)
  580.                             myErr = AESend(&aeEvent, &aeReply, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
  581.                                            kAENormalPriority, kAEDefaultTimeout, nil, nil);
  582.                     }
  583.                 }
  584.                 AEDisposeDesc(&aeEvent);
  585.             }
  586.         }
  587.     }
  588.     if ((Handle)DirAlias)
  589.         DisposHandle((Handle)DirAlias);
  590.     if ((Handle)FileAlias)
  591.         DisposHandle((Handle)FileAlias);
  592.     return(myErr);
  593. }
  594.  
  595.  
  596.  
  597. /* This runs through the process list looking for the indicated application */
  598. OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN, ProcessInfoRecPtr infoRecToFill)
  599. {
  600.     ProcessSerialNumber tempPSN;
  601.     OSErr myErr = noErr;
  602.     tempPSN.lowLongOfPSN = kNoProcess;
  603.     processSN->lowLongOfPSN = kNoProcess;
  604.     processSN->highLongOfPSN = kNoProcess;
  605.     do {
  606.         myErr = GetNextProcess(processSN);
  607.         if (myErr == noErr)
  608.             GetProcessInformation(processSN, infoRecToFill);
  609.     }
  610.             while ((infoRecToFill->processSignature != creatorToFind || infoRecToFill->processType != typeToFind) ||
  611.                    myErr != noErr);
  612.     
  613.     return(myErr);
  614. }
  615.  
  616. /*  BrowseFerMe calls the PPC browser and creates an AEAddressDesc out of the Browser */
  617. /* info if the user (you) doesn't cancel */
  618.  
  619. OSErr BrowseFerMe(void)
  620. {
  621.     OSErr myErr = noErr;
  622.     Str255 tWext;
  623.     
  624.     Str255 t2Wext;
  625.     GetIndString(tWext, kGenStrings, kPPCPrompt1);
  626.     GetIndString(t2Wext, kGenStrings, kPPCPrompt2);
  627.     myErr = PPCBrowser(tWext, &t2Wext, false, &theLoc, &theRec, gPPCFilterUPP, nil);
  628.     if (myErr == noErr) {
  629.         theID.name = theRec.name;
  630.         theID.location = theLoc;
  631.         myErr = AECreateDesc(typeTargetID, (Ptr)&theID, sizeof(theID), &myAddressDesc);
  632.     }
  633.     return(myErr);
  634. }
  635.  
  636. /* Show only FInders */
  637. pascal Boolean FinderFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  638. {
  639. #pragma unused (locationName)
  640.     OSType type;
  641.     
  642.     if (thePortInfo->name.portKindSelector == ppcByString) {
  643.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  644.         /* The BlockMove is so that we don't get an address error
  645.         ** on a 68000-based machine due to referencing a long at
  646.         ** an odd-address. */
  647.         if (type == kSysCreator)
  648.             return(true);
  649.     }
  650.     return(false);
  651. }
  652.  
  653. OSErr GetPathAndName(Str255 fullPath, Str255 appName)
  654. {
  655.     DialogPtr tdial = GetNewDialog(kPathDialog, nil, (WindowPtr)-1);
  656.     short hitItem = 0;
  657.     Str255 tempString;
  658.     short where;
  659.     ModalFilterProcPtr filterIt = nil;
  660.     
  661.     OSErr retVal = userCanceledErr;
  662.     SetDialogDefaultItem(tdial, ok);
  663.     SetDialogCancelItem(tdial, cancel);
  664.     SetDialogTracksCursor(tdial, true);
  665.     GetStdFilterProc(&filterIt);
  666.     ShowWindow(tdial);
  667.     DrawDialog(tdial);
  668.     do {
  669.         ModalDialog((ModalFilterProcPtr)filterIt, &hitItem);
  670.     }
  671.             while (hitItem != ok && hitItem != cancel);
  672.     if (hitItem == ok) {
  673.         GetIText((Handle)SnatchHandle(tdial, kEditLineItem), tempString);
  674.         /* now parse backwards to find the last colon, which is seperating the file name from the path */
  675.         where = tempString[0];
  676.         while (tempString[where] != kColon && where > 0)
  677.             where--;
  678.         if (where > 0) {
  679.             BlockMove((Ptr)&tempString[0], (Ptr)&appName[0], tempString[0] + 1);
  680.             BlockMove((Ptr)&tempString[0], (Ptr)&fullPath[0], where + 1);       /* include the colon */
  681.             fullPath[0] = where;
  682.             retVal = noErr;
  683.         }
  684.     }
  685.     DisposDialog(tdial);
  686.     
  687.     return(retVal);
  688. }
  689.  
  690. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
  691. {
  692.     short itemtype;
  693.     Rect itemrect;
  694.     Handle thandle;
  695.     
  696.     GetDItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
  697.     return((ControlHandle)thandle);
  698. }
  699.  
  700. /* end SnatchHandle */
  701.  
  702. pascal Boolean idleProc(EventRecord *eventIn, long *sleep, RgnHandle *mouseRgn)
  703. {
  704.     switch (eventIn->what) {
  705.         case nullEvent:
  706.             /* no nul processing in this sample */
  707.             *sleep = 0;
  708.             mouseRgn = nil;
  709.             break;
  710.         case updateEvt:
  711.         case activateEvt:
  712.             DrawMain((WindowPtr)eventIn->message);          /* draw whatever window needs an update */
  713.             break;
  714.         case app4Evt:
  715.             switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  716.                 case suspendResumeMessage:                  /* suspend/resume is also an activate/deactivate */
  717.                     gInBackground = (gERecord.message & kResumeMask) == 0;
  718.                     break;
  719.             }
  720.             break;
  721.             
  722.     }
  723.     return(false);                                          /* I'll wait forever */
  724. }
  725.  
  726.  
  727.  
  728. #pragma segment Initialize
  729. void InitalizeApp(void)
  730. {
  731.     MenuHandle helpHandle;
  732.     StringHandle helpString;
  733.     short count;
  734.     long vers;
  735.     MaxApplZone();
  736.     InitGraf((Ptr)&qd.thePort);
  737.     InitFonts();
  738.     InitWindows();
  739.     InitMenus();
  740.     TEInit();
  741.     InitDialogs(nil);
  742.     InitCursor();
  743.     /* Check system version */
  744.     Gestalt(gestaltSystemVersion, &vers);
  745.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  746.     if (vers < 7) {
  747.         StopAlert(kBadSystem, nil);
  748.         ExitToShell();
  749.     }
  750.     InitAEStuff();
  751.     
  752.     /* set up a PPCFilterUPP for use with the PPCBrowser */
  753.     gPPCFilterUPP = NewPPCFilterProc(FinderFilter);
  754.  
  755.     /* set up my menu junk */
  756.     gMymenu = GetNewMBar(kMBarID);
  757.     SetMenuBar(gMymenu);
  758.     gAppleMenuHandle = GetMHandle(kAppleMenu);
  759.     gFileMenuHandle = GetMHandle(kFileMenu);
  760.     gEditMenuHandle = GetMHandle(kEditMenu);
  761.     gToolMenuHandle = GetMHandle(kToolsMenu);
  762.     AddResMenu(gAppleMenuHandle, 'DRVR');
  763.     /* now install my Help menu item in the Help Manager's menu */
  764.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  765.     count = CountMItems(helpHandle);                        /* How many items are there? */
  766.     helpString = GetString(kHelpString);                    /* get my help string */
  767.     DetachResource(helpString);                             /* detach it */
  768.     HNoPurge(helpString);
  769.     MoveHHi((Handle)helpString);
  770.     HLock((Handle)helpString);
  771.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  772.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  773.     
  774.     DrawMenuBar();
  775.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  776. }
  777.